/*************************************************************************
 *                  HONGLING CAPITAL CONFIDENTIAL AND PROPRIETARY
 *
 *                COPYRIGHT (C) HONGLING CAPITAL CORPORATION 2012
 *    ALL RIGHTS RESERVED BY HONGLING CAPITAL CORPORATION. THIS PROGRAM
 * MUST BE USED  SOLELY FOR THE PURPOSE FOR WHICH IT WAS FURNISHED BY
 * HONGLING CAPITAL CORPORATION. NO PART OF THIS PROGRAM MAY BE REPRODUCED
 * OR DISCLOSED TO OTHERS,IN ANY FORM, WITHOUT THE PRIOR WRITTEN
 * PERMISSION OF HONGLING CAPITAL CORPORATION. USE OF COPYRIGHT NOTICE
 DOES NOT EVIDENCE PUBLICATION OF THE PROGRAM.
 *                  HONGLING CAPITAL CONFIDENTIAL AND PROPRIETARY
 *************************************************************************/

package com.springboot.common.config;

import com.springboot.common.jms.QueueMessageListener;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.ActiveMQPrefetchPolicy;
import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.connection.CachingConnectionFactory;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.listener.DefaultMessageListenerContainer;

import javax.jms.Queue;

/**
 * ActiveMQ的初始化配置类。
 *
 * @author hongchao zhao at 2019-5-23 15:25
 */
@Configuration
public class ActiveMQConfig {

    @Value("${spring.activemq.user}")
    private String usrName;

    @Value("${spring.activemq.password}")
    private  String password;

    @Value("${spring.activemq.broker-url}")
    private  String brokerUrl;

    @Value("${activemq.queue.request}")
    private String queueName;

    /**
     * 初始化消息队列。
     * @return
     */
    @Bean
    public Queue queueDestination(){
        return new ActiveMQQueue(queueName);
    }

    /**
     * 设置activeMq的属性，包括用户名密码以及基本配置。
     *
     * @return
     */
    @Bean
    public ActiveMQConnectionFactory activeMQConnectionFactory() {
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory();
        activeMQConnectionFactory.setBrokerURL(brokerUrl);
        activeMQConnectionFactory.setUserName(usrName);
        activeMQConnectionFactory.setPassword(password);
        //设置为异步发送消息
        activeMQConnectionFactory.setUseAsyncSend(true);
        //等待消息发送响应的时间。设置为0等待永远。
        activeMQConnectionFactory.setSendTimeout(5000);
        //预获取消息数量，每次处理1条消息，处理完再去取，同时动态开启多个消费者来处理消息，使得其它消费者不会被闲置下来
        ActiveMQPrefetchPolicy prefetchPolicy = new ActiveMQPrefetchPolicy();
        prefetchPolicy.setQueuePrefetch(1);
        activeMQConnectionFactory.setPrefetchPolicy(prefetchPolicy);

        return activeMQConnectionFactory;
    }

    /**
     * 配置JMS连接工厂，CachingConnectionFactory继承了SingleConnectionFactory，
     * 在保证同一连接的同时，增加了缓存的功能，可以缓存Session以及生产者，消费者。
     *
     * @return
     */
    @Bean
    public CachingConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory(activeMQConnectionFactory());
        //缓存session条数
        connectionFactory.setSessionCacheSize(100);
        connectionFactory.setCacheConsumers(false);
        return connectionFactory;
    }

    /**
     * 配置JMS模板（Queue，点对点队列模式），Spring提供的JMS工具类，它发送、接收消息。
     *
     * @return
     */
    @Bean
    public JmsTemplate jmsTemplate() {
        JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory());
        jmsTemplate.setDefaultDestination(queueDestination());
        //接收超时5秒
        jmsTemplate.setReceiveTimeout(5000);
        //true是topic，false是queue，默认是false，此处显示写出false
        jmsTemplate.setPubSubDomain(false);
        return jmsTemplate;
    }

    /**
     * 显示注入消息监听容器（Queue），配置连接工厂，监听的目标是bbsQueueDestination，监听器是上面定义的监听器。
     *
     * @return
     */
    @Bean
    public DefaultMessageListenerContainer queueListenerContainer() {
        DefaultMessageListenerContainer listenerContainer = new DefaultMessageListenerContainer();
        listenerContainer.setConnectionFactory(connectionFactory());
        //所说这里可以配置成通配符的【*】来监听所有队列
        listenerContainer.setDestination(queueDestination());
        listenerContainer.setMessageListener(new QueueMessageListener());
        //3-10表示最小并发数（concurrentConsumers）是3，最大并发数（maxConcurrentConsumers）为10，实际需要连接地址的queuePrefetch值配合
        listenerContainer.setConcurrency("3-10");
        listenerContainer.setCacheLevelName("CACHE_CONSUMER");
        listenerContainer.setReceiveTimeout(5000);
        listenerContainer.setSessionTransacted(false);
        listenerContainer.setIdleConsumerLimit(1);
        //AUTO_ACKNOWLEDGE = 1 ：自动确认；CLIENT_ACKNOWLEDGE = 2：客户端手动确认；DUPS_OK_ACKNOWLEDGE = 3： 自动批量确认；
        //SESSION_TRANSACTED = 0：事务提交并确认；INDIVIDUAL_ACKNOWLEDGE = 4：单条消息确认
        listenerContainer.setSessionAcknowledgeMode(4);
        return listenerContainer;
    }



}
